home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_08_10 / 8n10055a < prev    next >
Text File  |  1990-11-05  |  23KB  |  877 lines

  1. //////////////////////////////////////////////////////////////////////////
  2. //                                                                      //
  3. //                             ANTHILL                                  //
  4. //                                by                                    //
  5. //                     Mark Weaver and Alex Lane                        //
  6. //                                                                      //
  7. //////////////////////////////////////////////////////////////////////////
  8.  
  9. #include <graphics.h>
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <conio.h>
  13. #include <math.h>
  14. #include <dos.h>
  15. #include <ctype.h>
  16. #include <string.h>
  17. #include "anthill.h"
  18.                     
  19. #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
  20.  
  21. //////////////////////////////////////////////////////////////////////////
  22. //                                                                      //
  23. //                          Global Variables                            //
  24. //                                                                      //
  25. //////////////////////////////////////////////////////////////////////////
  26. float gfCellSizeX;              // Width (in pixels) of a cell
  27. float gfCellSizeY;              // Height (in pixels) of a cell
  28. unsigned guFoodUnits[100][100]; // How many units of food in each cell
  29. int gnTimeToHatch;              // Cycles required to become a worker ant
  30. int gnDropDistance;             // Distance at which to drop food for queen
  31. unsigned long gulTotalFood;     // Total units of food on board
  32. unsigned guWorkers;             // Total workers on board
  33. unsigned guEggs;                // Total number of eggs on board
  34. unsigned long gulCycle;         // Which life cycle are we in?
  35. unsigned guWorkersPortion;      // What a worker eats from each food packet
  36. unsigned guMaxLifeSpan;         // Longest life span
  37. unsigned guBirthRate;           // Percentage of cycles queen lays an egg
  38. unsigned guMaxSpeed;            // Maximum speed for worker ants
  39. unsigned guQueensEnergy;        // Queens extra starting energy level
  40. unsigned guInitEggs;            // Initial # of eggs
  41. unsigned guInitWorkers;         // Initial # of worker ants
  42. unsigned guInitFood;            // Initial # of cells with food
  43. unsigned guPause;               // Milliseconds to pause each cycle
  44. Queen *gQueen;                  // Queen ant
  45. Worker *headOfAntList;          // Head of linked list of worker ants
  46.  
  47.  
  48. //////////////////////////////////////////////////////////////////////////
  49. //                                                                      //
  50. //                        MOVER class functions                         //
  51. //                                                                      //
  52. //////////////////////////////////////////////////////////////////////////
  53.  
  54. Mover::Mover(unsigned uMaxRng, unsigned uMaxSpd, int nStartX, int nStartY)
  55. {
  56.   uMaxRange = uMaxRng;
  57.   uMaxSpeed = uMaxSpd;
  58.   nX = nInitX = nStartX;
  59.   nY = nInitY = nStartY;
  60.   bVisible = FALSE;
  61.   nVelX = -uMaxSpeed + random(uMaxSpeed + 1);
  62.   nVelY = -uMaxSpeed + random(uMaxSpeed + 1);
  63. }
  64.  
  65. int Mover::getX( void )
  66. {
  67. return nX;
  68. }
  69.  
  70. int Mover::getY( void )
  71. {
  72. return nY;
  73. }
  74.  
  75. BOOLEAN Mover::moveTo(int nNewX, int nNewY )
  76. {
  77.   if ((distance(nNewX, nNewY, nInitX, nInitY) <= uMaxRange || !uMaxRange)){
  78.     erase();
  79.      if ((nX = nNewX) < 0){
  80.         nX = 0;
  81.      }
  82.      else 
  83.         if (nX > 99) {
  84.             nX = 99;
  85.             }
  86.  
  87.      if ((nY = nNewY) < 0){
  88.         nY = 0;
  89.      }
  90.      else 
  91.         if (nY > 99) {
  92.         nY = 99;
  93.         }
  94.  
  95.      draw();
  96.      return( TRUE );
  97.   }
  98.   else {
  99.      return( FALSE );
  100.   }
  101. }
  102.  
  103. BOOLEAN Mover::move( void )
  104. {
  105.   int nNewX, nNewY;
  106.  
  107.   nNewX = nX + nVelX;
  108.   nNewY = nY + nVelY;
  109.  
  110.   if ((distance(nNewX, nNewY, nInitX, nInitY) <= uMaxRange || !uMaxRange)){
  111.     erase();
  112.      if ((nX = nNewX) < 0) {
  113.         nX = 0;
  114.         nVelX = -nVelX;
  115.      } 
  116.      else 
  117.         if (nX > 99) {
  118.             nX = 99;
  119.             nVelX = -nVelX;
  120.             }
  121.      if ((nY = nNewY) < 0) {
  122.         nY = 0;
  123.         nVelY = -nVelY;
  124.      }
  125.      else 
  126.         if (nY > 99) {
  127.         nY = 99;
  128.         nVelY = -nVelY;
  129.      }
  130.      draw();
  131.  
  132.     // Turn once in a while
  133.     if (random(100) < 10){
  134.       nVelX += random(3) - 1;
  135.       nVelY += random(3) - 1;
  136.         if (nVelX > uMaxSpeed) {
  137.           nVelX = uMaxSpeed;
  138.         }
  139.         else 
  140.             if (nVelX < -uMaxSpeed) {
  141.                 nVelX = -uMaxSpeed;
  142.             }
  143.  
  144.         if (nVelY > uMaxSpeed) { 
  145.           nVelY = uMaxSpeed;
  146.         }
  147.         else 
  148.             if (nVelY < -uMaxSpeed) {
  149.                 nVelY = -uMaxSpeed;
  150.             }
  151.  
  152.       // Make sure I do not stop
  153.         if (nVelX == 0 && nVelY == 0) {
  154.           nVelX = 1+random(uMaxSpeed-1);
  155.           nVelY = -1-random(uMaxSpeed-1);
  156.         }
  157.      }
  158.  
  159.      return( TRUE );
  160.   }
  161.   else {
  162.      draw();
  163.      return( FALSE );
  164.   }
  165. }
  166.  
  167. void Mover::show( void )
  168. {
  169.   if (!bVisible){
  170.      draw();
  171.      bVisible = TRUE;
  172.   }
  173. }
  174.  
  175. void Mover::erase( void )
  176. {
  177.   moverDrawFunc(nX, nY, FALSE, BACKGROUND );
  178. }
  179.  
  180. void Mover::draw( void )
  181. {
  182.   moverDrawFunc(nX, nY, TRUE, color);
  183. }
  184.  
  185. void Mover::moverDrawFunc(int nX, int nY, BOOLEAN bVisible, int nColor)
  186. {
  187.     setfillstyle(SOLID_FILL, bVisible ? nColor : BACKGROUND);
  188.     bar(nX * gfCellSizeX,        nY * gfCellSizeY,
  189.             (nX + 0.5) * gfCellSizeX, (nY + 1) * gfCellSizeY - 1);
  190.  
  191.  
  192. //////////////////////////////////////////////////////////////////////////
  193. //                                                                      //
  194. //                          ANT class functions                         //
  195. //                                                                      //
  196. //////////////////////////////////////////////////////////////////////////
  197.  
  198. Ant::Ant( int Range, int Speed, int nX, int nY, int Energy) :
  199.              Consumer( Energy ), // constructor 
  200.              Mover( Range, Speed, nX, nY ) // constructor
  201. {
  202.   bDead= FALSE;
  203. }
  204.  
  205. // Dying ant updates counters and drops any food he is carying
  206. void Ant::die(void)
  207. {
  208.   bDead = TRUE;
  209.   nEnergy = 0;
  210.   erase(); 
  211. }
  212.  
  213. void Ant::doTheAntThing(void)
  214. {
  215. // Age the ant
  216. nAge++;
  217.  
  218. // Every ant uses one energy unit per cycle
  219. nEnergy -= 1;
  220.  
  221. if (nEnergy<1 || nAge > nLifeSpan) {
  222.     die();
  223.     }
  224. else { 
  225.     if (bEgg) {
  226.         // force redraw in case egg has been walked on
  227.         moveTo(nX, nY); 
  228.         if (nAge > gnTimeToHatch) {
  229.             bEgg = FALSE;
  230.             color = GREEN;    
  231.             guEggs--;
  232.             guWorkers++;
  233.             }
  234.         }
  235.     }
  236. }
  237.  
  238. //////////////////////////////////////////////////////////////////////////
  239. //                                                                      //
  240. //                       QUEEN class functions                          //
  241. //                                                                      //
  242. //////////////////////////////////////////////////////////////////////////
  243.  
  244. Queen::Queen( unsigned InitEnergy, int QRange, int QSpeed, 
  245.                   int QIntitX, int QInitY, unsigned _birthRate ) : 
  246.     Ant(QRange, QSpeed, QIntitX, QInitY, random(100)+InitEnergy )
  247. {
  248.   birthRate = _birthRate;
  249.   color = YELLOW;
  250. }
  251.  
  252.  
  253. // Queen ant lays eggs once in a while
  254. void Queen::layEgg(void)
  255. {
  256.   new Worker(TRUE, nX, nY);
  257.   guEggs++;
  258.   nEnergy -= MIN(150, nEnergy);
  259. }
  260.  
  261.  
  262. void Queen::doTheAntThing(void)
  263. {
  264. // Every ant uses one energy unit per cycle
  265. nEnergy -= 1;
  266.  
  267. nVelX = random(uMaxSpeed+1)*(random(2) ? 1 : -1 );
  268. nVelY = random(uMaxSpeed+1)*(random(2) ? 1 : -1 );
  269.  
  270. if (nEnergy<1) {
  271.     die();
  272.     }
  273. else {
  274. // Turn around if at limits of area!
  275. if (distance(nInitX, nInitY, nX + nVelX, nY + nVelY) > uMaxRange) {
  276.     nVelX = -nVelX ;
  277.     nVelY = -nVelY ;
  278.     }
  279.                              
  280.     // Move somewhere
  281.     move();
  282.  
  283.     if (guFoodUnits[nX][nY]) {
  284.         eatFood(guFoodUnits[nX][nY]);
  285.         }
  286.     // need a minimum of 750 units to be able to lay an egg
  287.     // (the idea here is to conserve energy)
  288.     if ((nEnergy > 750) && (random(100) < birthRate)) {
  289.         layEgg();
  290.         }
  291.     // if the energy level gets too high, improve the chances of
  292.     // laying an egg; and vice versa
  293.     // keep the birthrate between 50 and 5 percent.
  294.     if ((nEnergy > 5000) && (birthRate < 49)) birthRate++;
  295.     if ((nEnergy < 3000) && (birthRate > 6)) birthRate--;
  296.     }
  297. }
  298.  
  299. //////////////////////////////////////////////////////////////////////////
  300. //                                                                      //
  301. //                       WORKER c